﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using YiNing.Tools.Args;
using YiNing.UI.Controls;

namespace YiNing.Tools
{
    public class WaferMappingHelper
    {
        public static string[,] MappingAnalysis(string filePath, ProductMappingArgs softwareMappingArgs)
        {
            string[,] data = null;
            try
            {
                if (File.Exists(filePath))
                {
                    string[] waferLines = WaferLinesDataClean(File.ReadAllLines(filePath));
                    //定义一个晶圆的二维数组
                    //data = new int[waferLines.Length, waferLines[0].Length];
                    for (int i = 0; i < waferLines.Length; i++)
                    {
                        AnalysisLine(ref data, i, waferLines[i], waferLines.Length, softwareMappingArgs.NotDieChar, softwareMappingArgs.DieSpiltChar, softwareMappingArgs.DieCharLenght);
                    }
                }
            }
            catch(Exception er)
            {

            }
            return data;
        }

        /// <summary>
        /// 晶圆行数据清洗
        /// </summary>
        /// <param name="contextLines">所有行数据</param>
        /// <param name="mixLength">每行清除空白字符后最小的长度限制</param>
        /// <returns></returns>
        private static string[] WaferLinesDataClean(string[] contextLines, int mixLength = 30)
        {
            List<string> res = new List<string>();
            foreach (var content in contextLines)
            {
                string temp = Regex.Replace(content, "[\\f\\r\\t\\v]+", "");
                if (temp.Equals("")) continue;
                res.Add(temp);
            }
            return res.ToArray();
        }

        /// <summary>
        /// 处理单行数据
        /// </summary>
        /// <param name="data"></param>
        /// <param name="lineIndex">行数</param>
        /// <param name="content">单行内容字符串</param>
        /// <param name="notChipStr">非芯片的标识</param>
        /// <param name="spilt">分隔符默认是没有分隔符</param>
        /// <param name="unitLength">表示一个芯片的字符长度默认是1</param>
        /// <param name="allWaferLine">表示总的晶圆行数,只有在data是空的时候才会有用</param>
        private static void AnalysisLine(ref string[,] data, int lineIndex, string content, int allWaferLine = 0, string notChipStr = "0", char spilt = '\0', int unitLength = 1)
        {
            if (content.Equals("")) return;
            // 如果是空的话，那么需要首先定义好
            if (data == null)
            {
                // 单行的芯片个数, 如果没有分隔符的话，那么就按照unitLength来截取, content.Length / unitLength 这个一定是可以整除的
                int rowChipNum = (spilt == '\0') ? content.Length / unitLength : content.Split(spilt).Length;
                data = new string[allWaferLine, rowChipNum];
            }
            if (spilt != '\0')
            {
                string[] cols = content.Split(spilt);
                for(int i=0; i< cols.Length;i++)
                {
                    data[lineIndex, i] = cols[i];
                }
            }
            else
            {
                int i = 0;
                while (content.Length >= unitLength)
                {
                    data[lineIndex, i] = content.Substring(0, unitLength);
                    content = content.Substring(unitLength);
                    i++;
                }
            }
        }


        #region 标准图谱
        /// <summary>
        /// 产品图谱数据转wafer aoi图谱
        /// </summary>
        /// <param name="softwareMappingArgs"></param>
        /// <param name="strData"></param>
        /// <returns></returns>
        public static Die[,] GetDiesData(ProductMappingArgs softwareMappingArgs, string[,] strData)
        {
            Die[,] dieData = new Die[strData.GetLength(1) + softwareMappingArgs.OffsetXNum * 2, strData.GetLength(0) + softwareMappingArgs.OffsetYNum * 2];

            try
            {
                for (int y = 0; y < dieData.GetLength(1); y++)
                {
                    for (int x = 0; x < dieData.GetLength(0); x++)
                    {
                        dieData[x, y] = new Die() { ColorIndex = Die.DefaultEdge, Enabled = false, IsEdge = true, XIndex = x, YIndex = y, };
                    }
                }


                for (int y = 0; y < strData.GetLength(1); y++)
                {
                    for (int x = 0; x < strData.GetLength(0); x++)
                    {
                        if (strData[x, y].Equals(softwareMappingArgs.NotDieChar)) continue;
                        string temp = strData[x, y].Substring(softwareMappingArgs.FilterDieCharStartIndex, softwareMappingArgs.FilterDieCharLength);
                        string id = strData[x, y].Substring(0, softwareMappingArgs.FilterDieCharStartIndex);
                        if ((temp.Equals(softwareMappingArgs.FilterDieChar) && softwareMappingArgs.FilterType == ProductMappingArgs.FilterTypeEnum.保留)||
                            (!temp.Equals(softwareMappingArgs.FilterDieChar) && softwareMappingArgs.FilterType == ProductMappingArgs.FilterTypeEnum.过滤 && !temp.Equals(softwareMappingArgs.NotDieChar)))
                        {
                            Die tempDie = dieData[y + softwareMappingArgs.OffsetXNum, x + softwareMappingArgs.OffsetYNum];
                            tempDie.ColorIndex = Die.DefaultUndo;
                            tempDie.Enabled = true;
                            tempDie.IsEdge = false;
                            tempDie.Id = id;
                        }
                        else if (!temp.Equals(softwareMappingArgs.NotDieChar))
                        {
                            Die tempDie = dieData[y + softwareMappingArgs.OffsetXNum, x + softwareMappingArgs.OffsetYNum];
                            tempDie.ColorIndex = Die.DefaultUnknown;
                            tempDie.Enabled = true;
                            tempDie.IsEdge = false;
                            tempDie.Id = id;
                        }
                    }
                }

            }
            catch (Exception er)
            {

            }
            return dieData;
        }

        /// <summary>
        /// 图谱数据旋转函数
        /// </summary>
        /// <param name="orignalData"></param>
        /// <param name="angle"></param>
        /// <returns></returns>
        public static Die[,] RotateMapping(Die[,] orignalData, int angle = 90)
        {
            if (orignalData == null) return null;
            /*
            原始数组x方向长度为oRNumX， y方向长度oRNumY
            原始点(x0, y0), 顺时针旋转90度后目标点(x1, y1)，两个点满足以下公式
           
            顺时针公式：已知x0，y0 求x1，y1
            x0 = y1
            y0 + X1 = oRNumY - 1

            逆时针公式: 已知x1，y1 求x0，y0
            x0 = y1
            y0 + X1 = oRNumX - 1
             */
            int oRNumX = orignalData.GetLength(0);
            int oRNumY = orignalData.GetLength(1);
            Die[,] rotatedDieData = new Die[oRNumY, oRNumX];

            for (int y = 0; y < rotatedDieData.GetLength(1); y++)
            {
                for (int x = 0; x < rotatedDieData.GetLength(0); x++)
                {
                    rotatedDieData[x, y] = new Die() { ColorIndex = Die.DefaultEdge, Enabled = false, IsEdge = true, XIndex = x, YIndex = y, };
                }
            }

            for (int y = 0; y < orignalData.GetLength(1); y++)
            {
                for (int x = 0; x < orignalData.GetLength(0); x++)
                {
                    if(angle > 0) // 顺时针
                    {
                        int tempXindex = rotatedDieData[oRNumY - 1 - y, x].XIndex;
                        int tempYindex = rotatedDieData[oRNumY - 1 - y, x].YIndex;
                        rotatedDieData[oRNumY - 1 - y, x] = orignalData[x, y];
                        rotatedDieData[oRNumY - 1 - y, x].XIndex = tempXindex;
                        rotatedDieData[oRNumY - 1 - y, x].YIndex = tempYindex;
                    }
                    else
                    {
                        int tempXindex = rotatedDieData[y, oRNumX - 1 - x].XIndex;
                        int tempYindex = rotatedDieData[y, oRNumX - 1 - x].YIndex;
                        rotatedDieData[y, oRNumX - 1 - x] = orignalData[x, y];
                        rotatedDieData[y, oRNumX - 1 - x].XIndex = tempXindex;
                        rotatedDieData[y, oRNumX - 1 - x].YIndex = tempYindex;
                    }
                }
            }

            return rotatedDieData;
        }

        /// <summary>
        /// 图谱对位操作，把产品图谱对应的ng信息映射到程式图谱
        /// </summary>
        /// <param name="sourceData"></param>
        /// <param name="targetData"></param>
        public static Die[,] MappingContraposition(Die[,] sourceData, Die[,] targetData, int xless = 0, int yless = 0)
        {
            if (xless < 0) xless = 0;
            if (yless < 0) yless = 0;
            Die[,] finalDies = targetData;
            try
            {
                for (int y = 0; y < finalDies.GetLength(1) - yless; y++)
                {
                    for (int x = 0; x < finalDies.GetLength(0) - xless; x++)
                    {
                        finalDies[x, y].ColorIndex = sourceData[x, y].ColorIndex;
                    }
                }
                return finalDies;
            }
            catch(Exception er)
            {
                //return null;
            }
            return finalDies;
        }

        public static List<Die> MappingContraposition(Die[,] sourceData, List<Die> targetData, int xless = 0, int yless = 0)
        {
            var finalDies = targetData;
            try
            {
                for (int y = 0; y < sourceData.GetLength(1) - yless; y++)
                {
                    for (int x = 0; x < sourceData.GetLength(0) - xless; x++)
                    {
                        var die = finalDies.Find(v => v.Id == sourceData[x, y].Id);
                        if (die == null) continue;
                        die.ColorIndex = sourceData[x, y].ColorIndex;
                    }
                }
                return finalDies;
            }
            catch (Exception er)
            {
                //return null;
            }
            return finalDies;
        }
        #endregion
    }
}
